package kayao.client.data;


import java.util.Vector;

import kayao.common.*;

public class King { 

	protected byte kingdom;
	protected Vector<Integer> slaves=null;

	public King(byte kingdom)
	{
		try
		{
			slaves=new Vector<Integer>();
			this.kingdom=kingdom;
			slaves.add(SharedMemory.getInstance().getMyself().getId());
		}
		catch(Exception e)
		{
			//Basic treatment at the moment... show message and restart the reading
			System.out.println("Error in King: The socket to listen couldn't be created: "+e.getMessage());
		}

	}
	/**
	 * It processes the first task from the queue (the index 0) and send the information to the host
	 * It deletes the task at the end
	 */
	public synchronized byte [] treatSuscriptersRequest(int kingdomInterested,String ip,
			String name, int id,byte teamid, int counter) {

		try 
		{
			if(kingdom!=kingdomInterested )
			{
				System.out.println("[King] I'm the king in: " + kingdom+ ", and they asked me for region: "+ kingdomInterested);
				//if the king has different kingdom or it's not a king anymore
				byte []data=new byte[9];
				byte []value=NetworkUtils.int32ToByte(KayaoValues.MAGIC_NUMBER);
				System.arraycopy(value, 0, data, 0, 4);
				data[4]=KayaoValues.SUSCRIPTION_REQUEST_NEGATIVE_ANSWER;
				NetworkUtils.insertIntToByteArray(data, 5, counter);
				return data;
			}
			else
			{
				//System.out.println("[King] Calculating suscripters for: Client ID: "+ id + " Name: "+ name+ " team: " + teamid +
				//		" Kingdom: "+ kingdomInterested);
				Client c=new Client(name, id, ip, teamid);
				//System.out.println("After created: "+c.getName());
				if(SharedMemory.getInstance().getClientById(c.getId())==null)
				{
					SharedMemory.getInstance().addClient(c);
					System.out.println("[King] Creating client. We didn't know him");
					slaves.add(c.getId());
				}
				else System.out.println("[King] Client already known.");
				
				Vector<Integer> subscribers=new Vector<Integer>();
				for(int i=0;i<slaves.size();i++)
				{
					if(slaves.get(i)==SharedMemory.getInstance().getMyself().getId())
						continue;
					else subscribers.add(slaves.get(i));
				}	
				SharedMemory.getInstance().updateSubscriberList(subscribers, kingdom);

				byte []data=new byte[calculateSizeAnswer(id,teamid)];
				byte []value=NetworkUtils.int32ToByte(KayaoValues.MAGIC_NUMBER);
				System.arraycopy(value, 0, data, 0, 4);
				data[4]=KayaoValues.SUSCRIPTION_REQUEST_ANSWER;
				NetworkUtils.insertIntToByteArray(data, 5, counter);
				int index=9;
				index=insertTeammates(data,index,id,teamid);
				index=insertEnemies(data,index,teamid);
				//We tell to the slave the subscribers
				//System.out.println("Printing from king: ");
				//for(int g=0; g<data.length;g++)
				//	System.out.print(data[g]);
				//System.out.println("");
				return data;
			}
		}
		catch (Exception e) 
		{
			System.out.println("Error in King.");
			e.printStackTrace();
			return null;
		} 
	}

	/**
	 * It calculates the size of the answer
	 * @param id
	 * @param teamid
	 * @return the amount of bytes
	 */
	private int calculateSizeAnswer(int id, int teamid) 
	{
		int size=0;
		//each client has 9+length
		for(int i=0;i<slaves.size();i++)
		{
			if(SharedMemory.getInstance().getClientById(slaves.get(i)).getTeam()!=teamid){
				Client cl = SharedMemory.getInstance().getClientById(slaves.get(i));
				//if(cl == null) System.out.println("Client null");
				int iddd = cl.getId();
				String name = cl.getName();
				//System.out.println("Name: "+name+" "+iddd);
				int len = name.length();
				size+=(9+len);
				//				size+=9+SharedMemory.getInstance().getClientById(slaves.get(i)).getName().length();
			}
			else if(SharedMemory.getInstance().getClientById(slaves.get(i)).getId()!=id )
				size+=4;
		}
		// +  headers + n� teammates + n enemies
		return size+9+2+2;
	}

	/**
	 * Insert the correspondent data for the enemies in the byte array
	 * @param data
	 * @param index
	 * @param teamid
	 * @return the new index
	 */
	private int insertEnemies(byte[] data, int index, byte teamid) 
	{
		//We cover the enemies inserting their information
		int n=0;
		//System.out.println("Size of slave vector: " + slaves.size());
		for(int i=0;i<slaves.size();i++)
			if(SharedMemory.getInstance().getClientById(slaves.get(i)).getTeam()!=teamid) 
				n++;
		byte []value=NetworkUtils.int32To2Bytes(n);
		System.arraycopy(value,0,data,index, 2);
		//System.out.println("Index of no of enemies: " + index);
		index+=2;

		for(int i=0;i<slaves.size();i++)
		{
			Client c=SharedMemory.getInstance().getClientById(slaves.get(i));
			if(c.getTeam()!=teamid)
			{

				//System.out.println("Writing enemies");
				byte []clientBytes=c.getBytes();
				System.arraycopy(clientBytes,1,data,index, clientBytes[0]);
				index+=clientBytes[0];
			}
		}

		return index;
	}

	/**
	 * It inserts in the data array the teammates' ids
	 * @param data
	 * @param index
	 * @param id
	 * @param teamid
	 * @return the new index
	 */
	private int insertTeammates(byte[] data, int index, int id, byte teamid)
	{
		int n=0;
		for(int i=0;i<slaves.size();i++)
			if(SharedMemory.getInstance().getClientById(slaves.get(i)).getTeam()==teamid)
				if(SharedMemory.getInstance().getClientById(slaves.get(i)).getId()!=id )
					n++;
		byte []value=NetworkUtils.int32To2Bytes(n);
		System.arraycopy(value,0,data,index, 2);
		index+=2;

		//We cover the teammates inserting the number of them (short) and their id (int32)
		for(int i=0;i<slaves.size();i++)
		{
			Client c=SharedMemory.getInstance().getClientById(slaves.get(i));
			if(c.getTeam()==teamid && c.getId()!=id )
			{
				value=NetworkUtils.int32ToByte(c.getId());
				//System.out.println("Inserting: "+c.getId()+" In: "+index);
				System.arraycopy(value,0,data,index,4);
				//System.out.println("Reading: "+NetworkUtils.insertByteArrayToInt(data, index));
				index+=4;
			}
		}

		return index;
	}

	public void removeSlave(int slaveid){
		for(int i=0;i<slaves.size(); i++){
			if(slaveid == slaves.get(i)){
				System.out.println("(King.removeSlave) SlaveID: "+slaveid+" was removed");
				slaves.remove(i);
			}
		}
	}

	public byte getKingdom()
	{
		return kingdom;
	}
	public Vector<Integer> getSlaves()
	{
		return slaves;
	}


}
